# -*- coding: utf-8 -*-
import datetime

from app import db

from flask_login import UserMixin

from werkzeug.security import check_password_hash, generate_password_hash


# 用户表
class User(UserMixin, db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def __init__(self, username, password):
        self.username = username
        self.password = password

    def is_authenticated(self):
        return True

    def is_active():
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return self.id

    def __repr__(self):
        return '%s' % self.username


# 交易账户表
class Account(db.Model):
    __tablename__ = 'account'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
    apikey = db.Column(db.String(80))
    secret = db.Column(db.String(80))
    status = db.Column(db.Integer)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    user = db.relationship('User',
                           backref=db.backref('accounts', lazy='dynamic'))

    def __init__(self, name, apikey, secret, user):
        self.name = name
        self.apikey = apikey
        self.secret = secret
        self.user = user
        self.status = 0

    def __repr__(self):
        return '%s(%r ,%r, %r, %r)' % (self.__class__.__name__, self.user_id,
                                       self.name, self.apikey, self.status)


# 月汇总表
class Summary(db.Model):
    __tablename__ = 'month_summary'
    id = db.Column(db.Integer, primary_key=True)
    year = db.Column(db.String(20))
    month = db.Column(db.String(20))
    last_asset = db.Column(db.Float)
    now_asset = db.Column(db.Float)
    # 本周期出入金额
    withdraw_amount = db.Column(db.Float)
    month_pnl_amount = db.Column(db.Float)
    month_pnl_ratio = db.Column(db.Float)
    profit_amount = db.Column(db.Float)
    loss_amount = db.Column(db.Float)
    profit_count = db.Column(db.Integer)
    loss_count = db.Column(db.Integer)
    month_accurcy = db.Column(db.Float)
    month_p_vs_l = db.Column(db.Float)

    account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
    account = db.relationship('Account',
                              backref=db.backref('summary_set',
                                                 lazy='dynamic'))

    def __init__(self, year, month, last_asset, now_asset, withdraw_amount,
                 month_pnl_amount, month_pnl_ratio, profit_amount, loss_amount,
                 profit_count, loss_count, month_accurcy, month_p_vs_l, account):
        self.year = year
        self.month = month
        self.last_asset = last_asset
        self.now_asset = now_asset
        self.withdraw_amount = withdraw_amount
        self.month_pnl_amount = month_pnl_amount
        self.month_pnl_ratio = month_pnl_ratio
        self.profit_amount = profit_amount
        self.loss_amount = loss_amount
        self.profit_count = profit_count
        self.loss_count = loss_count
        self.month_accurcy = month_accurcy
        self.month_p_vs_l = month_p_vs_l
        self.account = account

    def __repr__(self):
        return '%s(%r ,%r, %r, %r)' % (self.__class__.__name__,
                                       self.account_id, self.year, self.month,
                                       self.month_pnl_amount)


# 原始交易表
class TradingRecord(db.Model):
    __tablename__ = 'trading_record'
    id = db.Column(db.Integer, primary_key=True)
    # 日期时间字符串形式
    datetime = db.Column(db.String(40))
    contract = db.Column(db.String(40))
    #买为1，卖为-1
    buy = db.Column(db.Integer)
    price = db.Column(db.Float)
    amount = db.Column(db.Float)
    trans = db.Column(db.Float)
    fee = db.Column(db.Float)
    fee_type = db.Column(db.String(20))

    account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
    account = db.relationship('Account',
                              backref=db.backref('trading_record',
                                                 lazy='dynamic'))

    def __init__(self, datetime, contract, buy, price, amount,
                 trans, fee, fee_type, account):
        self.datetime = datetime
        self.contract = contract
        self.buy = buy
        self.price = price
        self.amount = amount
        self.trans = trans
        self.fee = fee
        self.fee_type = fee_type
        self.account = account

    def __repr__(self):
        return ('%s(%r ,%r, %r, %r, %r)'
                '' % (self.__class__.__name__, self.datetime,
                      self.contract, self.price, self.amount,
                      self.account_id))


# 动态持仓表，结构与交易记录一致，未平仓前放入该表
class Holding(db.Model):
    __tablename__ = 'holding'
    id = db.Column(db.Integer, primary_key=True)
    # 日期时间字符串形式
    dt = db.Column(db.String(40))
    # 日期时间时间戳形式，自动生成
    timestamp = db.Column(db.Float)
    contract = db.Column(db.String(40))
    serial = db.Column(db.Integer)
    # 多:1 / 空:-1
    direction = db.Column(db.Integer)
    price = db.Column(db.Float)
    amount = db.Column(db.Integer)
    trans = db.Column(db.Float)
    # 开仓:1 / 平仓:-1
    open = db.Column(db.Integer)
    fee = db.Column(db.Float)

    account_id = db.Column(db.String(40), db.ForeignKey('account.id'))
    account = db.relationship('Account',
                              backref=db.backref('holding_set', lazy='dynamic'))

    def __init__(self, dt, contract, serial, direction, price,
                 amount, trans, open, fee, account):
        self.dt = dt
        self.timestamp = datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")
        self.contract = contract
        self.serial = serial
        self.direction = direction
        self.price = price
        self.amount = amount
        self.trans = trans
        self.open = open
        self.fee = fee
        self.account = account

    def __repr__(self):
        return '%s(%r ,%r, %r, %r)' % (self.__class__.__name__, self.dt,
                                       self.contract, self.price, self.amount,
                                       self.account_id)


# 匹配记录表，完整的开/平仓记录
class PairTrading(db.Model):
    __tablename__ = 'pair_trading'
    id = db.Column(db.Integer, primary_key=True)
    # 开仓记录
    o_dt = db.Column(db.String(40))
    o_timestamp = db.Column(db.Float)
    o_contract = db.Column(db.String(40))
    o_serial = db.Column(db.Integer)
    o_direction = db.Column(db.Integer)
    o_price = db.Column(db.Float)
    o_amount = db.Column(db.Integer)
    o_trans = db.Column(db.Float)
    o_open = db.Column(db.Integer)
    o_fee = db.Column(db.Float)
    # 平仓记录
    c_dt = db.Column(db.String(40))
    c_timestamp = db.Column(db.Float)
    c_contract = db.Column(db.String(40))
    c_serial = db.Column(db.Integer)
    c_direction = db.Column(db.Integer)
    c_price = db.Column(db.Float)
    c_amount = db.Column(db.Integer)
    c_trans = db.Column(db.Float)
    c_open = db.Column(db.Integer)
    c_fee = db.Column(db.Float)

    account_id = db.Column(db.String(40), db.ForeignKey('account.id'))
    account = db.relationship('Account',
                              backref=db.backref('pair_set', lazy='dynamic'))

    def __init__(self, open_record, close_record, account):
        self.o_dt = open_record.dt
        self.o_timestamp = datetime.datetime.strptime(open_record.dt, "%Y-%m-%d %H:%M:%S")
        self.o_contract = open_record.contract
        self.o_serial = open_record.serial
        self.o_direction = open_record.direction
        self.o_price = open_record.price
        self.o_amount = open_record.amount
        self.o_trans = open_record.trans
        self.o_open = open_record.open
        self.o_fee = open_record.fee

        self.c_dt = close_record.dt
        self.c_timestamp = datetime.datetime.strptime(close_record.dt, "%Y-%m-%d %H:%M:%S")
        self.c_contract = close_record.contract
        self.c_serial = close_record.serial
        self.c_direction = close_record.direction
        self.c_price = close_record.price
        self.c_amount = close_record.amount
        self.c_trans = close_record.trans
        self.c_open = close_record.open
        self.c_fee = close_record.fee

        self.account = account

    def __repr__(self):
        return '%s(%r ,%r, %r, %r)' % (self.__class__.__name__, self.contract,
                                       self.o_dt, self.c_dt, self.price,
                                       self.account_id)


# 月度详细统计表，统计每一笔交易
class DetailAnalysis(db.Model):
    __tablename__ = 'detail_analysis'
    id = db.Column(db.Integer, primary_key=True)
    pnl_amount = db.Column(db.Float)
    pnl_ratio = db.Column(db.Float)
    max_floating_profit = db.Column(db.Float)
    max_floating_profit_index = db.Column(db.Integer)
    max_floating_loss = db.Column(db.Float)
    max_floating_loss_index = db.Column(db.Integer)
    max_wd_amount = db.Column(db.Float)
    max_wd_pct = db.Column(db.Float)
    max_wd_amount_index = db.Column(db.Integer)
    holding_cycle = db.Column(db.Integer)
    profit_cycle_start = db.Column(db.Integer)
    profit_cycle = db.Column(db.Integer)
    max_profit_cycle = db.Column(db.Integer)
    max_loss_cycle = db.Column(db.Integer)
    profit_limit_index = db.Column(db.Integer)
    img_url = db.Column(db.Text)

    pair_id = db.Column(db.Integer, db.ForeignKey('pair_trading.id'))
    pair = db.relationship('PairTrading',
                           backref=db.backref('detail', lazy='dynamic'))

    def __init__(self, pnl_amount, pnl_ratio, max_floating_profit,
                 max_floating_profit_index, max_floating_loss,
                 max_floating_loss_index, max_wd_amount, max_wd_pct,
                 max_wd_amount_index, holding_cycle,
                 profit_cycle_start, profit_cycle, max_profit_cycle,
                 max_loss_cycle, profit_limit_index, img_url, pair):
        self.pnl_amount = pnl_amount
        self.pnl_ratio = pnl_ratio
        self.max_floating_profit = max_floating_profit
        self.max_floating_profit_index = max_floating_profit_index
        self.max_floating_loss = max_floating_loss
        self.max_floating_loss_index = max_floating_loss_index
        self.max_wd_amount = max_wd_amount
        self.max_wd_pct = max_wd_pct
        self.max_wd_amount_index = max_wd_amount_index
        self.holding_cycle = holding_cycle
        self.profit_cycle_start = profit_cycle_start
        self.profit_cycle = profit_cycle
        self.max_profit_cycle = max_profit_cycle
        self.max_loss_cycle = max_loss_cycle
        self.profit_limit_index = profit_limit_index
        self.img_url = img_url
        self.pair = pair

    def __repr__(self):
        return '%s(%r ,%r, %r, %r)' % (self.__class__.__name__,
                                       self.pnl_amount, self.pair_id)
